<script lang="tsx">
import { defineComponent, ref, watch, onUnmounted } from 'vue';
import { ElMessage } from 'element-plus';
import { $t } from '@vben/locales';
import { obsUpload, obsDownload } from '#/utils/obs';

export default defineComponent({
  name: 'FileDoc',
  props: {
    uploadKey: {
      type: Number,
      default: 0,
    },
    modelValue: {
      type: String,
      default: '',
    },
    // 用于回显的文件信息
    fileInfo: {
      type: String,
      default: ''
    },
    // 文件类型：'zip'为压缩包，'doc'为文档
    fileType: {
      type: String,
      default: 'doc',
    },
  },
  emits: ['update:modelValue', 'change'],
  setup(props, { emit }) {
    const uploadRef = ref();
    const fileList = ref<Array<any>>([]);
    const currentFile = ref<any>(null);

    // 判断文件类型是否匹配
    const isFileTypeMatch = (fileName: string, fileType: string) => {
      const fileNameLower = fileName.toLowerCase();
      if (fileType === 'zip') {
        // 压缩包类型
        return fileNameLower.endsWith('.zip') || fileNameLower.endsWith('.rar') || fileNameLower.endsWith('.7z');
      } else {
        // 文档类型
        return fileNameLower.endsWith('.pdf') || fileNameLower.endsWith('.doc') || fileNameLower.endsWith('.docx') ||
          fileNameLower.endsWith('.ppt') || fileNameLower.endsWith('.pptx') || fileNameLower.endsWith('.xls') ||
          fileNameLower.endsWith('.xlsx');
      }
    };

    // 监听 modelValue 变化，用于回显
    watch(() => props.modelValue, (newValue) => {
      if (newValue && props.fileInfo && isFileTypeMatch(newValue, props.fileType)) {
        // 通过obs下载文件流获取文件URL
        obsDownload({
          Key: newValue
        }, (err: any, result: any) => {
          if (err) {
            console.error('获取文件失败:', err);
            return;
          }

          // 根据文件类型确定MIME类型
          const fileName = newValue;
          const mimeType = getMimeType(fileName);

          // 创建文件Blob URL
          const content = result.InterfaceResult.Content as ArrayBuffer;
          const blob = new Blob([content], {
            type: mimeType
          });
          const fileUrl = window.URL.createObjectURL(blob);

          currentFile.value = {
            name: fileName,
            url: fileUrl,
            isLocal: false,
            obsKey: newValue,
            mimeType
          };

          // 更新 fileList
          fileList.value = [{
            name: fileName,
            url: fileUrl,
            status: 'success'
          }];
        });
      } else {
        // 清空
        currentFile.value = null;
        fileList.value = [];
      }
    }, { immediate: true });

    // 获取文件MIME类型
    const getMimeType = (fileName: string) => {
      const ext = fileName.toLowerCase().split('.').pop();
      const mimeTypes: { [key: string]: string } = {
        'pdf': 'application/pdf',
        'doc': 'application/msword',
        'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'ppt': 'application/vnd.ms-powerpoint',
        'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
        'xls': 'application/vnd.ms-excel',
        'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'zip': 'application/zip',
        'rar': 'application/x-rar-compressed',
        '7z': 'application/x-7z-compressed'
      };
      return mimeTypes[ext || ''] || 'application/octet-stream';
    };

    // 文件上传相关处理函数
    const handleFileUploadSuccess = (response: any, file: any) => {
      console.log('response', response);
    };

    const handleFileUploadError = (error: any) => {
      console.error('文件上传失败:', error);
    };

    const handleFileUploadExceed = (files: any) => {
      ElMessage.error($t('competition.newsMgr.exceedTips'));
    };

    const handleFileUpload = async (options: any) => {
      const file = options.file;

      try {
        // 使用 obs 上传
        obsUpload({
          Key: file.name,
          SourceFile: file
        }, (err: any, result: any, path?: string) => {
          if (err) {
            ElMessage.error($t('competition.newsMgr.fileUploadError'));
            return;
          }

          if (path) {
            // 清理本地预览URL
            if (currentFile.value && currentFile.value.isLocal) {
              URL.revokeObjectURL(currentFile.value.url);
            }

            // 通过obs下载文件流获取文件URL
            obsDownload({
              Key: path
            }, (err: any, result: any) => {
              if (err) {
                console.error('获取文件失败:', err);
                ElMessage.error($t('competition.newsMgr.fileUploadError'));
                return;
              }

              // 创建文件Blob URL
              const content = result.InterfaceResult.Content as ArrayBuffer;
              const mimeType = getMimeType(file.name);
              const blob = new Blob([content], {
                type: mimeType
              });
              const fileUrl = window.URL.createObjectURL(blob);

              // 更新文件信息
              currentFile.value = {
                name: file.name,
                url: fileUrl,
                size: file.size,
                isLocal: false,
                obsKey: path,
                mimeType
              };

              // 更新 fileList
              fileList.value = [{
                name: file.name,
                url: fileUrl,
                status: 'success'
              }];

              // emit 更新值
              emit('update:modelValue', path);
              emit('change', {
                name: file.name,
                url: fileUrl,
                size: file.size,
                key: path
              });
            });
          }
        });
      } catch (error) {
        console.error('文件上传失败:', error);
        ElMessage.error($t('competition.newsMgr.fileUploadError'));
      }
    };

    const beforeFileUpload = (file: File) => {
      // 检查文件大小 (50MB)
      const isLt50M = file.size / 1024 / 1024 < 50;
      if (!isLt50M) {
        ElMessage.error($t('competition.newsMgr.fileSizeError'));
        return false;
      }

      // 检查文件类型
      const fileName = file.name.toLowerCase();
      if (props.fileType === 'zip') {
        // 压缩包类型
        const isCompressed = fileName.endsWith('.zip') || fileName.endsWith('.rar') || fileName.endsWith('.7z');
        if (!isCompressed) {
          ElMessage.error($t('competition.newsMgr.compressedFileFormatError'));
          return false;
        }
      } else {
        // 文档类型
        const isDocument = fileName.endsWith('.pdf') || fileName.endsWith('.doc') || fileName.endsWith('.docx') ||
          fileName.endsWith('.ppt') || fileName.endsWith('.pptx') || fileName.endsWith('.xls') ||
          fileName.endsWith('.xlsx');
        if (!isDocument) {
          ElMessage.error($t('competition.newsMgr.documentFormatError'));
          return false;
        }
      }

      return true;
    };

    // 移除文件
    const handleFileRemove = () => {
      // 清理URL（包括本地预览和obs下载的Blob URL）
      if (currentFile.value && currentFile.value.url) {
        URL.revokeObjectURL(currentFile.value.url);
      }
      currentFile.value = null;
      fileList.value = [];
      emit('update:modelValue', '');
      emit('change', null);
    };

    // 格式化文件大小
    const formatFileSize = (bytes: number) => {
      if (bytes === 0) return '0 B';
      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    };

    const handleFileChange = (file: any) => {
      console.log('file', file)
      // 在上传过程中显示本地文件预览
      if (file.raw) {
        const localUrl = URL.createObjectURL(file.raw);
        currentFile.value = {
          name: file.name,
          url: localUrl,
          size: file.size,
          isLocal: true,
          mimeType: getMimeType(file.name)
        };
      }
    };

    // 下载文件
    const downloadFile = () => {
      if (currentFile.value && currentFile.value.url) {
        const link = document.createElement('a');
        link.href = currentFile.value.url;
        link.download = currentFile.value.name;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
    };

    // 组件销毁时清理URL
    onUnmounted(() => {
      if (currentFile.value && currentFile.value.url) {
        URL.revokeObjectURL(currentFile.value.url);
      }
    });

    return {
      uploadRef,
      fileList,
      currentFile,
      isFileTypeMatch,
      handleFileUploadSuccess,
      handleFileUploadError,
      handleFileUploadExceed,
      handleFileUpload,
      beforeFileUpload,
      handleFileRemove,
      formatFileSize,
      handleFileChange,
      downloadFile
    }
  }
});


</script>
<template>
  <el-upload :key="uploadKey" class="upload-file-type" action="#" :limit="1"
    :accept="fileType === 'zip' ? '.rar,.zip,.7z' : '.pdf,.ppt,.doc'" v-model:file-list="fileList"
    :on-success="handleFileUploadSuccess" :on-error="handleFileUploadError" :before-upload="beforeFileUpload"
    :http-request="handleFileUpload" :on-exceed="handleFileUploadExceed">
    <el-button>{{ $t('competition.newsMgr.uploadFile') }}</el-button>
    <template #tip>
      <div class="upload-file-type-tip">{{ fileType === 'zip' ? $t('competition.newsMgr.fileTypeTips') :
        $t('competition.newsMgr.fileTypeTips2') }}</div>
    </template>
  </el-upload>
</template>
<style lang="scss" scoped>
// 上传组件样式
.upload-file-type {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: start;

  .el-upload .el-upload--text {
    flex-shrink: 0;
  }

  .upload-file-type-tip {
    flex-shrink: 0;
    margin-left: 8px;
    color: #909399;
    font-size: 12px;
  }

  :deep(.el-upload-list.el-upload-list--text) {
    flex: 1;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
}
</style>
